package com.smartian.dnshosts;

import android.text.TextUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

public class DnsHookProxyImpl {
    private final DnsHostList dnsHostList;
    private static Method sHolderMethod = null;

    public DnsHookProxyImpl(DnsHostList dnsHostList) {
        this.dnsHostList = dnsHostList;
    }

    public InetAddress[] lookupAllHostAddr(String hostname, int netId) throws UnknownHostException {
        boolean hostNameIsIpAddress = InetAddressUtils.isMatcherIpV4OrIpV6(hostname);
        if(hostNameIsIpAddress){
            return null;
        }
        String lookupIp = dnsHostList.lookup(hostname, netId);
        if(TextUtils.isEmpty(lookupIp)){
            return null;
        }
        InetAddress address = createInetAddress(hostname,lookupIp);
        return new InetAddress[]{
                address
        };
    }

    private InetAddress createInetAddress(String hostname, String lookupIp) {
        InetAddress inetAddress = null;
        try {
            if(InetAddressUtils.isIPv4LiteralAddress(lookupIp)) {
                Constructor<Inet4Address> declaredConstructor = Inet4Address.class.getDeclaredConstructor(String.class, byte[].class);
                declaredConstructor.setAccessible(true);
                inetAddress = declaredConstructor.newInstance(hostname, InetAddressUtils.textToNumericFormatV4(lookupIp));
            }else if(InetAddressUtils.isIPv6LiteralAddress(lookupIp)){
                Constructor<Inet6Address> declaredConstructor = Inet6Address.class.getDeclaredConstructor(String.class, byte[].class);
                declaredConstructor.setAccessible(true);
                inetAddress = declaredConstructor.newInstance(hostname, InetAddressUtils.textToNumericFormatV6(lookupIp));
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return inetAddress;
    }



    public boolean canLookup() {
        if(dnsHostList!=null && !dnsHostList.isEmpty()){
            return true;
        }
        return false;
    }

    public final static String METHODS[] = {
            "lookupAllHostAddr"
    };

    public boolean isHookMethod(String methodName) {
        return Arrays.asList(METHODS).contains(methodName);
    }
}
